#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syslog.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <signal.h>

#include "svfifo.hpp"

svfifo::svfifo()
{
    signal(SIGPIPE, SIG_IGN);           // 当管道接收端意外关闭时，会产生SIGPIPE信号，用signal(SIGPIPE, SIG_IGN)忽略掉这个信号，否则程序会被中止
}

svfifo::~svfifo()
{
    int i = 0;

    if (this->svWriteFIFOVec.size() > 0)
    {
        for (i = 0; i < this->svWriteFIFOVec.size(); i++)
        {
            if (this->svWriteFIFOVec[i].fd > 0)
            {
                close(this->svWriteFIFOVec[i].fd);
                this->svWriteFIFOVec[i].fd = -1;
            }
        }

        this->svWriteFIFOVec.clear();
    }

    if (this->svReadFIFOVec.size() > 0)
    {
        for (i = 0; i < this->svReadFIFOVec.size(); i++)
        {
            if (this->svReadFIFOVec[i].fd > 0)
            {
                close(this->svReadFIFOVec[i].fd);
                this->svReadFIFOVec[i].fd = -1;
            }
        }

        this->svReadFIFOVec.clear();
    }
}

int32_t svfifo::openWriteFIFO(std::string fifo_name)
{
    struct stfifo writeFIFO;

    if (access(fifo_name.c_str(), 0) != 0)
    {
        fprintf(stdout, "not create fifo %s\n", fifo_name.c_str());
        return -1;
    }

    writeFIFO.fifoName = fifo_name;
    writeFIFO.fd = open(fifo_name.c_str(), O_WRONLY | O_NONBLOCK);
    this->svWriteFIFOVec.push_back(writeFIFO);

    return writeFIFO.fd;
}

int32_t svfifo::writeFIFO(std::string fifo_name, char *data, int32_t data_len)
{
    int i = 0;
    int32_t ret = -1;

    assert(data);
    assert(data_len > 0);

    for (i = 0; i < this->svWriteFIFOVec.size(); i++)
    {
        if (this->svWriteFIFOVec[i].fifoName == fifo_name)
        {
            if (this->svWriteFIFOVec[i].fd < 0)
            {
                this->svWriteFIFOVec[i].fd = open(fifo_name.c_str(), O_WRONLY | O_NONBLOCK);
            }
            
            if (this->svWriteFIFOVec[i].fd > 0)
            {
                ret = write(this->svWriteFIFOVec[i].fd, data, data_len);
                if (ret < 0)
                {
                    close(this->svWriteFIFOVec[i].fd);
                    this->svWriteFIFOVec[i].fd = -1;
                }
            }
            break;
        }
    }

    return ret;
}

int32_t svfifo::closeWriteFIFO(std::string fifo_name)
{
    int i = 0;
    int32_t ret = -1;

    for (i = 0; i < this->svWriteFIFOVec.size(); i++)
    {
        if (this->svWriteFIFOVec[i].fifoName == fifo_name)
        {
            ret = close(this->svWriteFIFOVec[i].fd);
            this->svWriteFIFOVec[i].fd = -1;
            break;
        }
    }

    return ret;
}

int32_t svfifo::openReadFIFO(std::string fifo_name)
{
    struct stfifo readFIFO;

    if (access(fifo_name.c_str(), 0) != 0)
    {
        fprintf(stdout, "not create fifo %s\n", fifo_name.c_str());
        return -1;
    }

    readFIFO.fifoName = fifo_name;
    readFIFO.fd = open(fifo_name.c_str(), O_RDONLY | O_NONBLOCK);
    this->svReadFIFOVec.push_back(readFIFO);

    return readFIFO.fd;
}

int32_t svfifo::readFIFO(std::string fifo_name, char *buff, int32_t buff_len)
{
    int i = 0;
    int32_t ret = -1;

    assert(buff);
    assert(buff_len > 0);

    for (i = 0; i < this->svReadFIFOVec.size(); i++)
    {
        if (this->svReadFIFOVec[i].fifoName == fifo_name)
        {
            if (this->svReadFIFOVec[i].fd < 0)
            {
                this->svReadFIFOVec[i].fd = open(svReadFIFOVec[i].fifoName.c_str(), O_RDONLY | O_NONBLOCK);
            }
            
            if (this->svReadFIFOVec[i].fd > 0)
            {
                ret = read(this->svReadFIFOVec[i].fd, buff, buff_len);
            }
            break;
        }
    }

    return ret;
}

int32_t svfifo::closeReadFIFO(std::string fifo_name)
{
    int i = 0;
    int32_t ret = -1;

    for (i = 0; i < this->svReadFIFOVec.size(); i++)
    {
        if (this->svReadFIFOVec[i].fifoName == fifo_name)
        {
            ret = close(this->svReadFIFOVec[i].fd);
            this->svReadFIFOVec[i].fd = -1;
            break;
        }
    }

    return ret;
}